﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iTunesLib;
using System.Windows.Input;
using myTunes.Commands;
using System.Windows.Threading;
using System.ComponentModel;

namespace myTunes.BO
{
    public partial class TrackViewModel : INotifyPropertyChanged
    {
        internal IITTrack _iITTrack;
        private iTunesPlayer _iTunesPlayer;
        private TrackViewModelPlayPauseCommand _playPauseCommand;
        private int _pausePlayerPosition;
        private bool _shouldReleasePause;
        private bool _paused;

        public bool IsPaused
        {
            get { return _paused; }
        }
        
        public TrackViewModelPlayPauseCommand PlayPauseCommand
        {
            get { return _playPauseCommand; }        
        }

        public int PlayerPosition
        {
            get
            {
                return _iTunesPlayer.PlayerPosition;
            }
            set
            {
                _iTunesPlayer.PlayerPosition = value;
                if (_paused)
                    _pausePlayerPosition = value;
                RaisePropertyChanged("PlayerPosition");
            }
        }

        public string TimeInString 
        {
            get
            {
                int rest;
                long d = Math.DivRem(_iTunesPlayer.PlayerPosition, 60, out rest);
                return string.Format("{0}:{1}", d, rest.ToString().PadLeft(2, '0'));
            }
        }

        public TrackViewModel(IITTrack track, iTunesPlayer player)
        {
            _iITTrack = track;
            _iTunesPlayer = player;
            _playPauseCommand = new TrackViewModelPlayPauseCommand(this);
        }

        #region Properties

        public string Album 
        {
            get
            {
                return _iITTrack.Album;
            }
        }

        public string Artist
        {
            get
            {
                return _iITTrack.Artist;
            }
        }

        public int BitRate
        {
            get
            {
                return _iITTrack.BitRate;
            }
        }

        public int BPM
        {
            get
            {
                return _iITTrack.BPM;
            }
        }        

        public string Comment
        {
            get
            {
                return _iITTrack.Comment;
            }
        }

        public string Composer
        {
            get
            {
                return _iITTrack.Composer;
            }
        }        

        public int Duration
        {
            get
            {
                return _iITTrack.Duration;
            }
        }

        public string Genre
        {
            get
            {
                return _iITTrack.Genre;
            }
        }

        public int Index
        {
            get
            {
                return _iITTrack.Index;
            }
        }

        public string Kind
        {
            get
            {
                return _iITTrack.KindAsString;
            }
        }

        public string Name
        {
            get
            {
                return _iITTrack.Name;
            }
        }

        public int PlayedCount
        {
            get
            {
                return _iITTrack.PlayedCount;
            }
        }

        public int Rating
        {
            get
            {
                return _iITTrack.Rating;
            }
        }

        public int SampleRate
        {
            get
            {
                return _iITTrack.SampleRate;
            }
        }

        public int Size
        {
            get
            {
                return _iITTrack.Size;
            }
        }

        public TimeSpan Time
        {
            get
            {
                TimeSpan ts;
                string timeStr = _iITTrack.Time;
                if (timeStr.Split(':').Length <= 2)
                {
                    //<1 day
                    timeStr = timeStr.Insert(0, "00:");
                }

                TimeSpan.TryParse(timeStr, out ts);
                return ts;
            }
        }

        public int TrackCount
        {
            get
            {
                return _iITTrack.TrackCount;
            }
        }

        public int TrackID
        {
            get
            {
                return _iITTrack.trackID;
            }
        }

        public int TrackNumber
        {
            get
            {
                return _iITTrack.TrackNumber;
            }
        }

        public int Year
        {
            get
            {
                return _iITTrack.Year;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Alright, PlayPause is a little bit tricky ...
        /// When you listen to a track in a playlist, and you suddenly play a track from an other playlist, the PlayPause button in iTunes becomes a "Stop" button.
        /// Obviously, this happens because you are playing a track which is not part of the "visually selected" playlist.
        /// So when the user try to hit Pause, iTunes run "Stop" instead, which kind of sucks.
        /// The only way for iTunes to display a "Pause" button instead of "Stop" is to manually select the playlist which contains the new track we're playing,
        /// and unfortuantely the iTunes API doesn't provide such a thing.
        /// So here is what I've done. When the user click on "Pause", I actually mute the track, I save the current position of the track, then I run a timer
        /// which everytimes it ticks make the track return to the saved position. This gives the impression the track is actually suck => Paused.
        /// When the user hit the button again, I kill the timer, unmute the track, and let the music play...
        /// </summary>
        public void PlayPause()
        {
            if (_iTunesPlayer.PlayerState == ITPlayerState.ITPlayerStateStopped ||
                (_iTunesPlayer.CurrentPlaylist.CurrentTrack != null && _iTunesPlayer.CurrentPlaylist.CurrentTrack.TrackID != TrackID))
                _iTunesPlayer.CurrentPlaylist.PlayFirstTrack();
            else
            {
                if (_iTunesPlayer._iTunesApi.Mute)
                {
                    _shouldReleasePause = true;
                    _paused = false;
                    RaisePropertyChanged("IsPaused");
                }
                else
                {
                    _shouldReleasePause = false;
                    _paused = true;
                    RaisePropertyChanged("IsPaused");
                    StayInPause();
                }
                _iTunesPlayer._iTunesApi.Mute = !_iTunesPlayer._iTunesApi.Mute;
            }
        }

        private void StayInPause()
        {
            _pausePlayerPosition = _iTunesPlayer.PlayerPosition;
            DispatcherTimer timer = new DispatcherTimer();
            timer.Tick += (sender, e) =>
                {
                    if (_shouldReleasePause)
                    {
                        DispatcherTimer t = sender as DispatcherTimer;
                        t.Stop();
                        return;
                    }
                    _iTunesPlayer.PlayerPosition = _pausePlayerPosition;
                };
            timer.Interval = new TimeSpan(0, 0, 1);
            timer.Start();
        }

        #endregion
        

        public void RaisePropertiesChanged()
        {
            RaisePropertyChanged("PlayerPosition");
            RaisePropertyChanged("Duration");
            RaisePropertyChanged("TimeInString");
        }

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
